home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / WWW / analog / Source / utils.c < prev   
Encoding:
C/C++ Source or Header  |  1996-02-07  |  10.1 KB  |  461 lines

  1. /*** analog 1.9beta ***/
  2. /* Please read Readme.html, or http://www.statslab.cam.ac.uk/~sret1/analog/  */
  3.  
  4. /*** utils.c; lots of little functions to do odd little things ***/
  5.  
  6. #include "analhea2.h"
  7.  
  8. /* First, wildcard matching. This is restricted to at most one * (but any ?s).
  9.    NB argument order and return value different from HP/UX fnmatch() */
  10.  
  11. flag matchq(char *string, char *pattern, size_t n)
  12. {                      /* first, match with no *'s, up to n characters */
  13.   flag answer;
  14.  
  15.   for(answer = TRUE; answer == TRUE &&
  16.       (*string != '\0' || *pattern != '\0') && n > 0; n--) {
  17.     answer = (*string == *pattern || *pattern == '?');
  18.     string++;
  19.     pattern++;
  20.   }
  21.  
  22.   return(answer);
  23. }
  24.  
  25. flag wildmatch(char *string, char *pattern, char **w1, char **w2)
  26. {    /* w1 and w2 are changed to reflect part of string represented by * */
  27.   char *c;
  28.   flag answer;
  29.  
  30.   if ((c = strchr(pattern, '*')) == NULL) {
  31.     *w1 = string;
  32.     *w2 = string;
  33.     return(matchq(string, pattern, INFINITY));
  34.   }
  35.   else {
  36.     *c = '\0';
  37.     *w1 = string + strlen(pattern);
  38.     *w2 = string + MAX(strlen(string) - strlen(c + 1), 0);
  39.     answer = (matchq(string, pattern, strlen(pattern))) &&
  40.       (matchq(*w2, c + 1, INFINITY));
  41.     *c = '*';
  42.     return(answer);
  43.   }
  44. }
  45.  
  46. int strtomonth(char month[3])  /* convert 3 letter month abbrev. to int */
  47. {
  48.   int monthno = ERR;
  49.  
  50.   switch (month[0]) {
  51.   case 'A':
  52.     switch (month[1]) {
  53.     case 'p':
  54.       monthno = 3;
  55.       break;
  56.     case 'u':
  57.       monthno = 7;
  58.       break;
  59.     }
  60.     break;
  61.     case 'D':
  62.     monthno = 11;
  63.       break;
  64.   case 'F':
  65.     monthno = 1;
  66.     break;
  67.     case 'J':
  68.     switch (month[1]) {
  69.     case 'a':
  70.       monthno = 0;
  71.       break;
  72.     case 'u':
  73.       switch (month[2]) {
  74.       case 'l':
  75.     monthno = 6;
  76.     break;
  77.       case 'n':
  78.     monthno = 5;
  79.     break;
  80.       }
  81.       break;
  82.     }
  83.     break;
  84.   case 'M':
  85.     switch (month[2]) {
  86.     case 'r':
  87.       monthno = 2;
  88.       break;
  89.     case 'y':
  90.       monthno = 4;
  91.       break;
  92.     }
  93.     break;
  94.   case 'N':
  95.     monthno = 10;
  96.     break;
  97.   case 'O':
  98.     monthno = 9;
  99.       break;
  100.   case 'S':
  101.     monthno = 8;
  102.     break;
  103.   }
  104.  
  105.   return(monthno);
  106.  
  107. }
  108.  
  109. int dayofdate(int date, int monthno, int year)  /* day of week of given date */
  110. {
  111.   extern int dateoffset[];
  112.  
  113.   int x;
  114.   x = dateoffset[monthno] + date + year + (year / 4) + 5 -
  115.     ISLEAPJF(monthno, year);
  116.   return(x % 7);
  117. }
  118.  
  119. int minsbetween(int date1, int monthno1, int year1, int hr1, int min1,
  120.         int date2, int monthno2, int year2, int hr2, int min2)
  121. {
  122.   extern int dateoffset[];
  123.  
  124.   int x, y;
  125.   x = dateoffset[monthno1] + date1 + year1 * 365 + (year1 / 4) -
  126.     ISLEAPJF(monthno1, year1);
  127.   y = dateoffset[monthno2] + date2 + year2 * 365 + (year2 / 4) -
  128.     ISLEAPJF(monthno2, year2);
  129.  
  130.   return((y - x) * 1440 + (hr2 - hr1) * 60 + (min2 - min1));
  131. }
  132.  
  133. long timecode(int date, int monthno, int year, int hr, int min)
  134. {   /* calculate a 'timecode', i.e. increasing function of time */
  135.  
  136.   return((year - 1990) * 535680 +       /* 60 * 24 * 31 * 12 */
  137.      monthno * 44640 +
  138.      date * 1440 +
  139.      hr * 60 +
  140.      min);
  141. }
  142.  
  143. struct timestruct startofweek(struct timestruct atime)
  144. {  /* given a time, what is the time at the start of that week? */
  145.  
  146.   extern int monthlength[];
  147.  
  148.   extern int weekbeginson;
  149.  
  150.   struct timestruct answer;
  151.   int day;
  152.   
  153.   day = dayofdate(atime.date, atime.monthno, atime.year);
  154.  
  155.   answer.date = atime.date - day + weekbeginson;
  156.            /* giving a weekbeginson-day in [date - 6, date + 6] */
  157.   if (answer.date > atime.date)
  158.     answer.date -= 7;
  159.   answer.monthno = atime.monthno;
  160.   answer.year = atime.year;
  161.  
  162.   if (answer.date <= 0) {
  163.     answer.monthno--;
  164.     if (answer.monthno == -1) {
  165.       answer.monthno = 11;
  166.       answer.year--;
  167.     }
  168.     answer.date = monthlength[answer.monthno] + answer.date +
  169.       ISLEAPFEB(answer.monthno, answer.year);
  170.   }
  171.  
  172.   answer.code = timecode(answer.date, answer.monthno, answer.year,
  173.              answer.hr = 0, answer.min = 0);
  174.  
  175.   return(answer);
  176.  
  177. }
  178.  
  179. FILE *fopenlog(char *name, char logtype[12], flag *ispipe)
  180. {             /* open a logfile with a particular name for reading */
  181.  
  182.   extern char commandname[];
  183.   extern struct loglist *uncompresshead;
  184.   extern flag warnq;
  185.  
  186.   FILE *f;
  187.   struct loglist *uncompressp;
  188.   char *w1, *w2;
  189.   char command[MAXSTRINGLENGTH];
  190.  
  191.   *ispipe = OFF;
  192.  
  193.   if (STREQ(name, "stdin"))
  194.     f = stdin;
  195.   else {
  196.     f = fopen(name, "r");
  197.     if (f == NULL) {
  198.       if (warnq)
  199.     fprintf(stderr, "%s: Warning: Failed to open %s %s: ignoring it\n",
  200.         commandname, logtype, name);
  201.     }
  202.     else for (uncompressp = uncompresshead; uncompressp -> name[0] != '\0' &&
  203.           !(*ispipe); uncompressp = uncompressp -> next) {
  204.       if (wildmatch(name, uncompressp -> name, &w1, &w2)) {
  205.     fclose(f);
  206.     strcpy(command, uncompressp -> prefix);
  207.     strcat(command, " ");
  208.     strcat(command, name);
  209.     f = popen(command, "r");
  210.     *ispipe = ON;
  211.       }
  212.     }
  213.   }
  214.  
  215.   return(f);
  216. }
  217.  
  218. int fcloselog(FILE *f, char *name, char logtype[12], flag ispipe)
  219. {                 /* close it again */
  220.  
  221.   extern char commandname[];
  222.   extern flag warnq;
  223.  
  224.   int rc;
  225.  
  226.   if (!ispipe)
  227.     rc = fclose(f);    /* Not much can go wrong with fclose. I hope. */
  228.   else if ((rc = pclose(f)) != 0 && warnq)
  229.       fprintf(stderr, "%s: Warning: Problems uncompressing %s %s\n",
  230.           commandname, logtype, name);
  231.  
  232.   return(rc);
  233. }
  234.  
  235. void int3printf(FILE *outf, int x)
  236.                     /* print +ve integer with separators every 3 digits */
  237. {
  238.   extern char sepchar;
  239.  
  240.   int i = 1;
  241.  
  242.   if (sepchar == '\0')
  243.     fprintf(outf, "%d", x);
  244.  
  245.   else {
  246.     while (x / 1000 >= i)   /* i * 1000 might overflow */
  247.       i *= 1000;     /* find how big x is, so we know where to start */
  248.  
  249.     fprintf(outf, "%d", (x / i) % 1000);
  250.                            /* now run down again, printing each clump */
  251.  
  252.     for ( i /= 1000; i >= 1; i /= 1000)
  253.       fprintf(outf, "%c%03d", sepchar, (x / i) % 1000);
  254.   }
  255. }
  256.  
  257. void double3printf(FILE *outf, double x)
  258.                          /* the same, only with +ve integer doubles */
  259. {
  260.   extern char sepchar;
  261.  
  262.   int i = 0;
  263.  
  264.   if (x < 0.5)
  265.     fprintf(outf, "0");
  266.  
  267.   else if (sepchar == '\0')
  268.     fprintf(outf, "%.0f", x);
  269.  
  270.   else {
  271.  
  272.     while (x >= 1000) {
  273.       x /= 1000;
  274.       i++;
  275.     }
  276.  
  277.     fprintf(outf, "%d", (int)ROUND(x));
  278.  
  279.     for ( ; i >= 1; i--) {
  280.       x -= (int)x;
  281.       x *= 1000;
  282.       fprintf(outf, "%c%03d", sepchar, (int)ROUND(x));
  283.     }
  284.  
  285.   }
  286.  
  287. }
  288.  
  289. void doublefprintf(FILE *outf, double x)
  290. {                 /* print a double in %f format without trailing zeros */
  291.   int prec;
  292.   double d;
  293.  
  294.   /* first calculate how many decimal places we need */
  295.  
  296.   d = x;
  297.   for (prec = 0; d - floor(d + 0.000005) > 0.00001; prec++)
  298.     d *= 10;
  299.  
  300.   /* now print it */
  301.  
  302.   fprintf(outf, "%.*f", prec, x);
  303. }
  304.  
  305. void *xmalloc(size_t size)
  306. {    /* the same as malloc, only checks for out of memory */
  307.  
  308.   extern char commandname[];
  309.   extern flag sq;
  310.  
  311.   void *answer;
  312.  
  313.   if ((answer = malloc(size)) == NULL) {
  314.     fprintf(stderr, "%s: Ran out of memory: cannot continue\n", commandname);
  315.     if (sq == ON)
  316.       fprintf(stderr, "  Try turning hostname counting off or using approximate host counting");
  317.     exit(ERR);
  318.   }
  319.  
  320.   else
  321.     return(answer);
  322. }
  323.  
  324. void *xcalloc(int nelem, int elsize)
  325. {    /* ditto calloc */
  326.  
  327.   extern char commandname[];
  328.   extern flag sq;
  329.  
  330.   void *answer;
  331.  
  332.   if ((answer = calloc((size_t)nelem, (size_t)elsize)) == NULL) {
  333.     fprintf(stderr, "%s: Ran out of memory: cannot continue\n", commandname);
  334.     if (sq == ON)
  335.       fprintf(stderr, "  Try turning hostname counting off or using approximate host counting");
  336.     exit(ERR);
  337.   }
  338.  
  339.   else
  340.     return(answer);
  341. }
  342.  
  343. char *strtolower(char *string)
  344. {         /* convert a string to lower case */
  345.  
  346.   char *c;
  347.  
  348.   for (c = string; *c != '\0'; c++)
  349.     *c = tolower(*c);
  350.  
  351.   return(string);
  352. }
  353.  
  354. char *strtoupper(char *string)
  355. {         /* convert a string to upper case */
  356.  
  357.   char *c;
  358.  
  359.   for (c = string; *c != '\0'; c++)
  360.     *c = toupper(*c);
  361.  
  362.   return(string);
  363. }
  364.  
  365. int magicno(char *string, int base)
  366. {          /* convert a string to a magic number (using c_i.2^i mod b) */
  367.  
  368.   int answer;
  369.   int i;
  370.  
  371.   answer = 0;
  372.   for (i = 0; string[i] != '\0'; i++) {
  373.     answer += answer + string[i];
  374.     if (answer < 0)
  375.       answer = -answer;
  376.     while (answer >= base)
  377.       answer -= base;
  378.   }
  379.  
  380.   return(answer);
  381. }
  382.  
  383. int hoststrcmp(char *hostn1, char *hostn2)
  384. {   /* given two reversed hostnames, what is their "alphabetical" order? */
  385.  
  386.   char hostn1cpy[MAXSTRINGLENGTH], hostn2cpy[MAXSTRINGLENGTH];
  387.   char *part11, *part12, *part13, *part14, *part2;
  388.   int tempint1, tempint2;
  389.  
  390.   if (!isdigit(*hostn1)) {
  391.     if (isdigit(*hostn2))
  392.       return(-1);    /* all numbers come after all letters */
  393.     else
  394.       return(strcmp(hostn1, hostn2));   /* both non-numbers; usual alphabet */
  395.   }
  396.   else if (!isdigit(*hostn2))
  397.     return(1);
  398.   else  {
  399.     /* the difficult case; both numerical. Convert bits to numbers */
  400.     strcpy(hostn1cpy, hostn1);   /* because strtok destroys the string */
  401.     strcpy(hostn2cpy, hostn2);
  402.     part11 = strtok(hostn1cpy, ".");
  403.     part12 = strtok((char *)NULL, ".");
  404.     part13 = strtok((char *)NULL, ".");
  405.     part14 = strtok((char *)NULL, ".");
  406.  
  407.     part2 = strtok(hostn2cpy, ".");
  408.     tempint1 = atoi(part11);
  409.     tempint2 = atoi(part2);
  410.     if (tempint1 != tempint2)
  411.       return(tempint1 - tempint2);
  412.     else {
  413.       part2 = strtok((char *)NULL, ".");
  414.       if (part12 == NULL && part2 == NULL)
  415.     return(0);
  416.       else if (part12 == NULL)
  417.     return(-999);
  418.       else if (part2 == NULL)
  419.     return(999);
  420.       else {
  421.     tempint1 = atoi(part12);
  422.     tempint2 = atoi(part2);
  423.     if (tempint1 != tempint2)
  424.       return(tempint1 - tempint2);
  425.     else {
  426.       part2 = strtok((char *)NULL, ".");
  427.       if (part13 == NULL && part2 == NULL)
  428.         return(0);
  429.       else if (part13 == NULL)
  430.         return(-999);
  431.       else if (part2 == NULL)
  432.         return(999);
  433.       else {
  434.         tempint1 = atoi(part13);
  435.         tempint2 = atoi(part2);
  436.         if (tempint1 != tempint2)
  437.           return(tempint1 - tempint2);
  438.         else {
  439.           part2 = strtok((char *)NULL, ".");
  440.           if (part14 == NULL && part2 == NULL)
  441.         return(0);
  442.           else if (part14 == NULL)
  443.         return(-999);
  444.           else if (part2 == NULL)
  445.         return(999);
  446.           else {
  447.         tempint1 = atoi(part14);
  448.         tempint2 = atoi(part2);
  449.         if (tempint1 != tempint2)
  450.           return(tempint1 - tempint2);
  451.         else
  452.           return(0);
  453.           }
  454.         }
  455.       }
  456.     }
  457.       }
  458.     }
  459.   }
  460. }
  461.